package com.zzld.modules.wechat.oauth;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.concurrent.ExecutionException;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;

import com.zzld.core.utils.MD5Util;
import com.zzld.modules.wechat.util.ConfKit;
import com.zzld.modules.wechat.util.HttpKit;


 /**
  * 微信支付相关封装
  * @author 张楠
  *
  */
public class Pay {

    // 发货通知接口
    private static final String DELIVERNOTIFY_URL = "https://api.weixin.qq.com/pay/delivernotify?access_token=";
    private static final String UNIFIEDORDER  =  "https://api.mch.weixin.qq.com/pay/unifiedorder";
    
    
    
    /**
     * 获取预付订单ID
     * @param params
     * @return
     * @throws IOException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static String getPrepayid(Map<String,String> params) throws  IOException, ExecutionException,InterruptedException{
    	String xml = HttpKit.post(UNIFIEDORDER,getPackage(params));
         if (StringUtils.isNotBlank(xml)) {
        	 xml = xml.replaceAll("<![CDATA[|]]>", "");
			String prepay_id = Jsoup.parse(xml).select("prepay_id").html();
			if (prepay_id != null){
				return prepay_id;
			}
				
         }
         return null;
    }
    
    /**
     * 参与 paySign 签名的字段包括：appid、timestamp、noncestr、package 以及 appkey。
     * @param params
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String getPackage(Map<String, String> params) throws UnsupportedEncodingException{
		String sign = packageSign(params,ConfKit.get("partnerKey"));
		params.put("sign", sign); 
		StringBuilder xml = new StringBuilder();
		xml.append("<xml>\n");
		for (Map.Entry<String, String> entry : params.entrySet()) {
			if ("body".equals(entry.getKey()) || "sign".equals(entry.getKey())) {
				xml.append("<" + entry.getKey() + "><![CDATA[").append(entry.getValue()).append("]]></" + entry.getKey() + ">\n");
			} else {
				xml.append("<" + entry.getKey() + ">").append(entry.getValue()).append("</" + entry.getKey() + ">\n");
			}
		}
		xml.append("</xml>");
		return xml.toString();
	}
    
    
    /**
     * 构造package签名
     * @param params
     * @param paternerKey
     * @return
     * @throws UnsupportedEncodingException 
     */
    private static String packageSign(Map<String, String> params, String paternerKey) throws UnsupportedEncodingException {
    	 String string1 = createSign(params, false);
         String stringSignTemp = string1 + "&key=" + paternerKey;
         return  DigestUtils.md5Hex(stringSignTemp).toUpperCase();
    }
    
 
    
    /**
	 * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
	 */
	public static String createSign(SortedMap<String, String> packageParams, String AppKey) {
		StringBuffer sb = new StringBuffer();
		Set es = packageParams.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + AppKey);
		String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
		return sign;
	}
    
    
 

    /**
     * 构造签名
     * @param params
     * @param encode
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static String createSign(Map<String, String> params, boolean encode) throws UnsupportedEncodingException {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuffer temp = new StringBuffer();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = value.toString();
            }
            if (encode) {
                temp.append(URLEncoder.encode(valueString, "UTF-8"));
            } else {
                temp.append(valueString);
            }
        }
        return temp.toString();
    }   
}
